﻿/* ***********************************************************************************************
 * Oak_DynamicSeek
 * Version: 1.0
 * Author:  BRyan Solero  
 * Email:  arindil@gmail.com
 * Copyright 2012.  All Rights Reserved.
 * 
 * ************************************************************************************************/
using System;
using System.Collections.Generic;


using Microsoft.Xna.Framework;
using OakEngine.AI.Dynamic_Steering_Behavior;

namespace OakEngine.AI.Flocking
{
    public class Oak_Flock
    {
        private List<Oak_DynamicSteeringBehavior> m_Boids;
        public List<Oak_DynamicSteeringBehavior> Boids { get { return m_Boids; } set { m_Boids = value; } } 
        private bool[] m_bisInArea;
        private int flocksize;

        public Oak_Flock(int amount)
        {
            m_Boids = new List<Oak_DynamicSteeringBehavior>(amount);
            m_bisInArea = new bool[amount];
            flocksize = amount;
        }

        public int SetArea(Oak_DynamicSteeringBehavior boid, float size, float minDotProduct = -1.0f)
        {
            Vector2 lookVector = Vector2.Zero;
            if (minDotProduct > -1.0f)
            {
                lookVector = boid.GetRotationAsVelocity();
            }


            Oak_Flock result;
            int count = 0;
            for (int i = 0; i < flocksize; i++)
            {
                Oak_DynamicSteeringBehavior b = m_Boids[i];
                m_bisInArea[i] = false;

                // If this is us we are checking then continue
                if(b == boid)
                    continue;

                //Check for distance
                if (Vector2.Distance(boid.Position, b.Position) > size)
                {
                    continue;
                }

                // Check Angle
                if (minDotProduct > -1.0f)
                {
                    Vector2 offset = b.Position - boid.Position;
                    offset = Vector2.Normalize(offset);
                    if ((lookVector.X * offset.X < minDotProduct) && 
                        (lookVector.Y * offset.Y < minDotProduct))
                    {
                        continue;
                    }
                }


                m_bisInArea[i] = true;
                count++;
            }

            return count;
        }

        public Vector2 GetAreaCenter()
        {
            Vector2 center = Vector2.Zero;
            int count = 0;
            for (int i = 0; i < flocksize; i++)
            {
                if (m_bisInArea[i])
                {
                    center += m_Boids[i].Position;
                    count++;
                }
            }

            center *= 1.0f / (float)count;

            return center;
        }

        public Vector2 GetAverageDirection()
        {
            Vector2 center = Vector2.Zero;
            int count = 0;
            for (int i = 0; i < flocksize; i++)
            {
                if (m_bisInArea[i])
                {
                    center += m_Boids[i].Direction;
                    count++;
                }
            }

            center *= 1.0f / (float)count;

            return center;
        }
    }
}
